# -*- coding: utf8 -*-
#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import webapp2
import jinja2
import logging
from datetime import datetime, date
import os
import json
from model import Entry, Category, Geodata
from google.appengine.ext import db
from google.appengine.api import users, urlfetch
from gaesessions import get_current_session

jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(os.path.dirname(__file__)))
user = users.get_current_user()
cats = [''] + map(lambda x: x.name, db.GqlQuery("SELECT * FROM Category WHERE uid = :1", user))

class MainHandler(webapp2.RequestHandler):
    def get(self):#{{{
		echo = self.response.out.write
		date_sep = '-'
		endl = '<br />\n'

		global user
		user = users.get_current_user()

		#set latlngmap
		latlngmap = {}
		for g in Geodata.all():
			latlngmap[g.addr] = {
				'formatted_addr': g.formatted_addr,
				'lat': g.lat,
				'lng': g.lng,
			}

		#get the min date to calculate statistics
		n = 3
		now = date.today()
		if now.month < n + 1:
			dateth = datetime(now.year - 1, now.month - n + 12, 1)
		else:
			dateth = datetime(now.year, now.month - n, 1)

		cats = [''] + map(lambda x: x.name, db.GqlQuery("SELECT * FROM Category WHERE uid = :1", user))

		#initialize stats
		#stats = [dict(zip(cats, [0 for i in range(len(cats))])) for i in range(n + 1)]
		stats = [dict() for i in range(n + 1)]

		template = jinja_env.get_template(os.path.join('', 'main.jinja'))
		ents = db.GqlQuery("SELECT * FROM Entry WHERE uid = :1 ORDER BY date ASC", user)
		itemcomp, addrcomp, cmtcomp = [set() for i in range(3)]
		for e in ents:
			itemcomp.add(e.item)
			if len(e.loc): addrcomp.add(e.loc)
			if len(e.comment): cmtcomp.add(e.comment)
			if e.date >= dateth:
				ind = abs(e.date.month - now.month)
				if e.cat not in stats[ind]:
					stats[ind][e.cat] = e.val
				else:
					stats[ind][e.cat] += e.val
				if 'yearmonth' not in stats[ind]:
					stats[ind]['yearmonth'] = '%d%s%d' % (e.date.year, date_sep , e.date.month)

		stats = [sorted([(k, stat[k]) for k in stat]) for stat in stats][::-1]
		tpvals = {
			'entries': ents,
			'user': user,
			'logout_url': users.create_logout_url('/'),
			'cats': cats,
			'cats_json': json.dumps(cats),
			'itemcomp': json.dumps(sorted(itemcomp)),
			'addrcomp': json.dumps(sorted(addrcomp)),
			'cmtcomp': json.dumps(sorted(cmtcomp)),
			'stats': json.dumps(stats),
			'latlngmap': json.dumps(latlngmap)
		}
		self.response.out.write(template.render(tpvals))
		return#}}}


class ajax_insc(webapp2.RequestHandler):
	def post(self):#{{{
		ret = dict()
		name = self.request.get('name')
		if not user:
			ret['ret'] = False
			self.response.out.write(json.dumps(ret))
			return
		cat = Category(uid = user, name = name, key_name = name)
		cat.put()
		ret['ret'] = True
		self.response.out.write(json.dumps(ret))
		return#}}}


class ajax_inse(webapp2.RequestHandler):
	def post(self):#{{{
		rget = self.request.get
		ret = dict()
		logging.info('val is ' + rget('val'))
		if not user:
			ret['ret'] = False
			self.response.out.write(json.dumps(ret))
			return
		ent = Entry(uid = user,
					date = datetime.strptime(rget('date'), '%Y-%m-%d'),
					insdate = datetime.now(),
					item = rget('item'),
					loc = rget('loc'),
					val = int(rget('val')),
					cat = rget('cat'),
					comment = rget('comment'))
		ent.put()
		faddr = rget('formatted_addr')
		if faddr:
			Geodata(addr = rget('loc'), formatted_addr = faddr, lat = rget('lat'), lng = rget('lng'), key_name = addr).put()
		ret['ret'] = True
		ret['id'] = ent.key().id()
		self.response.out.write(json.dumps(ret))
		return#}}}


class ajax_insgeo(webapp2.RequestHandler):
	def post(self):
		rget = self.request.get
		addr = rget('addr')
		faddr = rget('faddr')
		lat = rget('lat')
		lng = rget('lng')
		Geodata(addr = addr, formatted_addr = faddr, lat = rget('lat'), lng = rget('lng'), key_name = addr).put()
		return


class ajax_dele(webapp2.RequestHandler):
	def post(self):#{{{
		get = self.request.get
		ret = {}
		e = db.get(db.Key.from_path('Entry', int(get('id'))))
		if e is None:
			ret['ret'] = False
			self.response.out.write(json.dumps(ret))
			return
		e.delete()
		ret['ret'] = True
		self.response.out.write(json.dumps(ret))
		return#}}}


class ajax_list_table(webapp2.RequestHandler):
	def post(self):#{{{
		ents = db.GqlQuery("SELECT * FROM Entry WHERE UID = :1", self.request.get('uid'))
		for ent in ents:
			echo('<tr><td>%d</td><td>%s</td><td>%f</td><td>%s</td><td>%s</td></tr>' % (ent.eid, ent.cat, ent.val, ent.loc, ent.comment))
		return#}}}


class ins(webapp2.RequestHandler):
	def get(self):#{{{
		echo = self.response.out.write
		endl = '<br />\n'

		fh = open('latlng.txt', 'r')
		for line in fh:
			addr, faddr, lat, lng = line.decode('utf8').strip().split(' ')
			Geodata(addr = addr, formatted_addr = faddr, lat = lat, lng = lng, key_name = addr).put()
		fh.close()

		fh = open('receipt.txt', 'r')
		for line in fh:
			fields = line.decode('utf8').split(' ')
			datestr = fields[0] + ' ' + fields[1]
			date = datetime.strptime(datestr, '%Y/%m/%d %H:%M')
			loc, cat, item, val = fields[2:6]
			cmt = ''
			if len(fields) > 6 and fields[6] != '\n':
				cmt = fields[6].strip()
			Entry(uid = user, item = item, val = int(val), cat = cat, date = date, insdate = datetime.now(), loc = loc, comment = cmt).put()
			Category(uid = user, name = cat, key_name = cat).put()
			echo("1 inserted" + endl)
			echo('%s %s %s %s %s' % (date, item, val, cat, loc) + endl)
		fh.close()
		return#}}}


class trunc(webapp2.RequestHandler):
	def get(self):#{{{
		for e in Entry.all().filter('uid =', user):
			e.delete()
		for c in Category.all().filter('uid =', user):
			c.delete()
		return#}}}


class dumpe(webapp2.RequestHandler):
	def get(self):#{{{
		for e in Entry.all():
			self.response.out.write('%s %s %s %d %s %s %s<br />' % (e.uid, e.date, e.item, e.val, e.loc, e.cat, e.comment))
		return#}}}


class dumpc(webapp2.RequestHandler):
	def get(self):#{{{
		for c in Category.all():
			self.response.out.write('%s %s<br />\n' % (c.uid, c.name))
		return#}}}


class test(webapp2.RequestHandler):
	def get(self):#{{{
		n = 3
		now = date.today()
		if now.month < n + 1:
			dateth = datetime(now.year - 1, now.month - n + 12, 1)
		else:
			dateth = datetime(now.year, now.month - n, 1)
		ents = db.GqlQuery("SELECT * FROM Entry WHERE date > :1", dateth)
		#stats = [dict(zip(cats, [0 for i in range(len(cats))])) for i in range(n + 1)]
		stats = [dict() for i in range(n + 1)]
		for e in ents:
			#self.response.out.write('%s %s %s %d %s %s %s<br />' % (e.uid, e.date, e.item, e.val, e.loc, e.cat, e.comment))
			ind = abs(e.date.month - now.month)
			if e.cat not in stats[ind]:
				stats[ind][e.cat] = 0
			else:
				stats[ind][e.cat] += e.val
		stats = [sorted([(k, stat[k]) for k in stat]) for stat in stats][::-1]
		for stat in stats:
			self.response.out.write(str(stat) + '<br />')
		return#}}}


class latlng(webapp2.RequestHandler):
	def get(self):
		addr = self.request.get('addr')
		url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' + addr + '&sensor=false'
		res = urlfetch.fetch(url = url)
		content = res.content
		res = json.loads(content)
		self.response.out.write('%s %s %f %f<br />' % (addr, res.formatted_address, res.geometry.location.lat, res.geometry.location.lng))
		return


app = webapp2.WSGIApplication([
	('/', MainHandler),
	('/ajax_inse', ajax_inse),
	('/ajax_insc', ajax_insc),
	('/ajax_insgeo', ajax_insgeo),
	('/ajax_dele', ajax_dele),
	#('/ajax_list_table', ajax_list_table),
	('/ins', ins),
	('/trunc', trunc),
	#('/dumpe', dumpe),
	#('/dumpc', dumpc),
	#('/latlng', latlng),
	('/test', test)
], debug = True)
